/*
 * MultiStipulation.java
 *
 * Created on August 4, 2005, 8:50 PM
 *
 * To change this basis, choose Tools | Options and locate the basis under
 * the Source Creation and Management node. Right-click the basis and choose
 * Open. You can then make changes to the basis in the Source Editor.
 */

package com.xucia.jsponic.data;

import java.util.Map;
import java.util.TreeMap;

/**
 *
 * @author kris.zyp
 */
public class MultiStipulation implements Stipulation {
    public enum Operator {AND, OR, XOR, EQUALS};
    /** Creates a new instance of MultiStipulation */
    public MultiStipulation() {
    }
    public static Stipulation createStipulation(String str) {
        String[] strings;
        strings = str.split(" AND ");
        if (strings.length > 1) {
            MultiStipulation stipulation = new MultiStipulation();
            stipulation.stipulationA = createStipulation(strings[0]);
            stipulation.stipulationB = createStipulation(strings[1]);
            stipulation.operator = Operator.AND;
            return stipulation;
        }
        strings = str.split(" OR ");
        if (strings.length > 1) {
            MultiStipulation stipulation = new MultiStipulation();
            stipulation.stipulationA = createStipulation(strings[0]);
            stipulation.stipulationB = createStipulation(strings[1]);
            stipulation.operator = Operator.OR;
            return stipulation; 
        }
        strings = str.split(" XOR ");
        if (strings.length > 1) {
            MultiStipulation stipulation = new MultiStipulation();
            stipulation.stipulationA = createStipulation(strings[0]);
            stipulation.stipulationB = createStipulation(strings[1]);
            stipulation.operator = Operator.XOR;
            return stipulation;
        }
        return SimpleStipulation.createStipulation(str);
    }

    public Stipulation stipulationA;
    public Stipulation stipulationB;
    public Operator operator = Operator.AND;

    public boolean qualifies(Object obj) {
        if (operator == Operator.AND) 
            return stipulationA.qualifies(obj) && stipulationB.qualifies(obj);
        if (operator == Operator.OR) 
            return stipulationA.qualifies(obj) || stipulationB.qualifies(obj);
        if (operator == Operator.XOR) 
            return stipulationA.qualifies(obj) != stipulationB.qualifies(obj);
        if (operator == Operator.EQUALS) 
            return stipulationA.qualifies(obj) == stipulationB.qualifies(obj);
        throw new RuntimeException ("Invalid operator " + operator + "specified in stipulation ");
    }
    @Override
	public String toString() {
        if (operator == Operator.AND) 
            return stipulationA + " AND " + stipulationB;
        if (operator == Operator.OR) 
            return stipulationA + " OR " + stipulationB;
        if (operator == Operator.XOR) 
            return stipulationA + " XOR " + stipulationB;
        if (operator == Operator.EQUALS) 
            return stipulationA + "=" + stipulationB;
        throw new RuntimeException ("Invalid operator " + operator + "specified in stipulation ");
    }

    public Map getNameValueMap() {
        Map nameValueMap = new TreeMap();        
        addToNameValueMap(nameValueMap);
        return nameValueMap;
    }

    public void addToNameValueMap(java.util.Map map) {
        stipulationA.addToNameValueMap(map);
        stipulationB.addToNameValueMap(map);
    }

    @Override
	public MultiStipulation clone() {
        try {
            MultiStipulation stipulation = (MultiStipulation) super.clone();
            stipulation.stipulationA = this.stipulationA.clone();
            stipulation.stipulationB = this.stipulationB.clone();
            return stipulation;
        }
        catch (CloneNotSupportedException e) {
            throw new RuntimeException(e);
        }
        
    }
	@Override
	public boolean equals(Object obj) {
		if (obj instanceof MultiStipulation) {
			return (((MultiStipulation)obj).operator==operator && 
					((MultiStipulation)obj).stipulationA.equals(stipulationA) &&
					((MultiStipulation)obj).stipulationB.equals(stipulationB));				
		}
		return false;
	}
	@Override
	public int hashCode() {
		// TODO Auto-generated method stub
		return stipulationA.hashCode() + stipulationB.hashCode() + operator.hashCode();
	}

}
